package com.sociesc.findasmartphonespark.wekaUtils;

import com.sociesc.findasmartphonespark.model.AccessPoint;
import weka.classifiers.bayes.BayesNet;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.converters.ArffLoader;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class geraArff {

	/**
	 * @param args
	 * @throws java.io.IOException
	 */

	static String relation = "wifis";   // nome do relacionamento usado no arquivo ARFF do Weka

	static String[] parts;

	static ArrayList<String> nomeSalas = new ArrayList<>();              // nome das salas identificadas, sem repetir
	static ArrayList<String> nomeAp = new ArrayList<>();                 // nome dos APs identifacados, sem repetir
	static ArrayList<String> key = new ArrayList<>();                    // chave primaria
	static ArrayList<String> contagem = new ArrayList<>();               // codigos das contagems
	static ArrayList<AccessPoint> AccessPoints = new ArrayList<>();      // lista de access points final
	static ArrayList<AccessPoint> tempAccessPoints = new ArrayList<>();  // lista de access points temporaria, gera a final

	/* Objetivo: 	gerar arquivo arff de uma lista de arquivos .txt
	 * Parametros:	entrada - caminho onde estão os arquivos de texto
	 * Retorno: 	1 se o arquivo foi gerado, 2 se ocorreu erro
	 */
	public static String iniciar(File entrada, String saida) throws IOException {
		String retorno = "";
		if (entrada.exists()){
			listFilesForFolder(entrada);
			retorno = geraArff(saida);

			return retorno;
		} else {
			return "erro, pasta de entrada nao existe\n";
		}
	}

	/**
	 * Geral: Mostra os arquivos da pasta informada
	 *
	 * @param folder
	 *            pasta onde est�o os arquivos
	 *
	 *     @todo: alterar para utilizar somente um arquivo
	 */
	public static void listFilesForFolder(final File folder) throws IOException {
		for (final File fileEntry : folder.listFiles()) {
			if (fileEntry.isDirectory()) {
				listFilesForFolder(fileEntry);
			} else {
				// cont += 1;
				loadData(fileEntry);
			}
		}
	}

	/**
	 * Cria arrays com mac da rede, sinal, sala, e identificador unico da
	 * contagem
	 *
	 * @param file
	 *            um arquivo com as informacoes do sinal
	 */
	public static void loadData(File file) throws IOException {
		String line;
		String uuid = UUID.randomUUID().toString();

		/*
		 * Contagem contagem = new Contagem();
		 *
		 * contagem.setUuid(uuid); contagem.setQuantidade(0);
		 */

		BufferedReader br = new BufferedReader(new FileReader(file));

		tempAccessPoints.clear();

		while ((line = br.readLine()) != null) {
			AccessPoint AccessPoint = new AccessPoint();

			// System.out.println(line);
			parts = line.split("\\x7C"); // \\x7C = | em ASCII

			AccessPoint.setSSID(parts[0]);
			AccessPoint.setBSSID(parts[1]);
			AccessPoint.setRSSI(Double.parseDouble(parts[2]));
			AccessPoint.setSala(parts[3]);
			// AccessPoint.setContagem(uuid);
			AccessPoint.setContagem(parts[4]);

			tempAccessPoints.add(AccessPoint);

			if (!nomeSalas.contains(parts[3])) {
				nomeSalas.add(parts[3]);
			}
			if (!nomeAp.contains(parts[1])) {
				nomeAp.add(parts[1]);
			}
		}

		contagem.add(uuid);

		AccessPoints.addAll(normalize(tempAccessPoints));

		br.close();
	}

	public static ArrayList<AccessPoint> normalize(ArrayList<AccessPoint> lista)
			throws IOException {

		ArrayList<AccessPoint> listaRetorno = new ArrayList<>();

		double average = 0;
		double finalsum = 0;

		for (int i = 0; i < lista.size(); i++) {
			finalsum += lista.get(i).getRSSI();
		}

		average = finalsum / (lista.size());

		double std = StandardDeviationCalc.stdDev(lista);

		System.out.println(std);

		if (std == 0){
			std = 1;
		}

		for (int i = 0; i < lista.size(); i++) {
			AccessPoint ap = new AccessPoint();

			ap.setBSSID(lista.get(i).getBSSID());
			ap.setSSID(lista.get(i).getSSID());
			ap.setRSSI((lista.get(i).getRSSI() - average) / std);
			ap.setSala(lista.get(i).getSala());
			ap.setContagem(lista.get(i).getContagem());

			listaRetorno.add(ap);
		}
		// System.out.println(listaRetorno);

		return listaRetorno;
	}

	public static String geraArff(String saida) {
		Writer writer = null;
		String sinal = "";
		File file = new File(saida);

		try {
			if (!file.exists()) {
				file.createNewFile();
			} else {
				file.delete();
				file.createNewFile();
			}

			writer = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(file), "utf-8"));

			writer.write("%Titulo:\n%Fontes:\n%Informações úteis:\n\n@RELATION "
					+ relation + "\n\n");

			for (int i = 0; i < nomeAp.size(); i++) {
				writer.write("@ATTRIBUTE \"" + nomeAp.get(i) + "\" REAL\n");
			}

			writer.write("@ATTRIBUTE class {");
			for (int i = 0; i < nomeSalas.size(); i++) {
				if (i + 1 == nomeSalas.size()) {
					writer.write(nomeSalas.get(i) + "}\n\n");
				} else {
					writer.write(nomeSalas.get(i) + ",");
				}
			}

			writer.write("@DATA\n");

			for (int i = 0; i < nomeSalas.size(); i++) {
				for (int j = 1; j <= 5; j++) { // contagem
					for (int k = 0; k < nomeAp.size(); k++) {
						for (int m = 0; m < AccessPoints.size(); m++) {
							//BinarySearch.search1(nomeAp, AccessPoints.get(m).getSSID());
							if (AccessPoints.get(m).getBSSID()
									.equals(nomeAp.get(k))
									&& AccessPoints.get(m).getSala()
									.equals(nomeSalas.get(i))
									&& Integer.parseInt(AccessPoints.get(m)
									.getContagem()) == j) {
								sinal = AccessPoints.get(m).getRSSI() + ",";
								break;
							}
						}
						if (sinal != "") {
							writer.write(sinal);
							sinal = "";
						} else {
							writer.write("0,");
							sinal = "";
						}

					}
					writer.write(nomeSalas.get(i) + "\n");
				}
			}
		} catch (IOException ex) {
			// report
			return ex.toString();
		} finally {
			try {
				writer.close();
				return "1";
			} catch (Exception ex) {
				return ex.toString();
			}
		}
	}

	public static String geraArffJson(ArrayList<AccessPoint> aps, String saida) {
		Writer writer = null;
		String sinal = "";
		File file = new File(saida);

		try {
			aps = normalize(aps);
		} catch (IOException e) {
			e.printStackTrace();
			return e.toString();
		}

		nomeSalas.clear();
		nomeAp.clear();

		for (int i = 0; i < aps.size(); i++) {
			if (!nomeSalas.contains(aps.get(i).getSala())) {
				nomeSalas.add(aps.get(i).getSala());
				System.out.println("------ geraArffJson - Sala: " + aps.get(i).getSala());
			}
			if (!nomeAp.contains(aps.get(i).getBSSID())) {
				nomeAp.add(aps.get(i).getBSSID());
				System.out.println("------ geraArffJson - BSSID: " + aps.get(i).getBSSID());
			}
		}

		try {
			if (!file.exists()) {
				file.createNewFile();
			} else {
				file.delete();
				file.createNewFile();
			}

			writer = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(file), "utf-8"));

			writer.write("%Titulo:\n%Fontes:\n%Informações úteis:\n\n@RELATION "
					+ relation + "\n\n");

			for (int i = 0; i < nomeAp.size(); i++) {
				writer.write("@ATTRIBUTE \"" + nomeAp.get(i) + "\" REAL\n");
			}

			writer.write("@ATTRIBUTE class {");
			for (int i = 0; i < nomeSalas.size(); i++) {
				if (i + 1 == nomeSalas.size()) {
					writer.write(nomeSalas.get(i) + "}\n\n");
				} else {
					writer.write(nomeSalas.get(i) + ",");
				}
			}

			writer.write("@DATA\n");

			for (int i = 0; i < nomeSalas.size(); i++) {
				/*for (int j = 1; j <= 5; j++) { // contagem */
					for (int k = 0; k < nomeAp.size(); k++) {
						for (int m = 0; m < aps.size(); m++) {
							//BinarySearch.search1(nomeAp, AccessPoints.get(m).getSSID());
							if (aps.get(m).getBSSID()
									.equals(nomeAp.get(k))
									&& aps.get(m).getSala()
									.equals(nomeSalas.get(i))) /*
									&& Integer.parseInt(aps.get(m)
									.getContagem()) == j) */ {
								sinal = aps.get(m).getRSSI() + ",";
								break;
							}
						}
						if (sinal != "") {
							writer.write(sinal);
							System.out.println("------ geraArffJson - Rssi: " + sinal);
							sinal = "";
						} else {
							writer.write("0,");
							System.out.println("------ geraArffJson - Rssi: " + sinal);
							sinal = "";
						}

					}
					writer.write(nomeSalas.get(i) + "\n");
				/*}*/
			}
		} catch (IOException ex) {
			// report
			return ex.toString();
		} finally {
			try {
				writer.close();
				return "1";
			} catch (Exception ex) {
				return ex.toString();
			}
		}
	}


	public static String geraArffJson2(ArrayList<AccessPoint> aps, String saida) {
		Writer writer = null;
		String sinal = "";
		File file = new File(saida);

		try {
			aps = normalize(aps);
		} catch (IOException e) {
			e.printStackTrace();
			return e.toString();
		}

		nomeSalas.clear();
		nomeAp.clear();

		for (int i = 0; i < aps.size(); i++) {
			System.out.println("Sinal: " + aps.get(i).getRSSI());
			if (!nomeSalas.contains(aps.get(i).getSala())) {
				nomeSalas.add(aps.get(i).getSala());
				System.out.println("------ geraArffJson - Sala: " + aps.get(i).getSala());
			}
			if (!nomeAp.contains(aps.get(i).getBSSID())) {
				nomeAp.add(aps.get(i).getBSSID());
				System.out.println("------ geraArffJson - BSSID: " + aps.get(i).getBSSID());
			}
		}

		try {
			writer = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(file), "utf-8"));

			writer.write("%Titulo:\n%Fontes:\n%Informações úteis:\n\n@RELATION "
					+ relation + "\n\n");

			for (int i = 0; i < nomeAp.size(); i++) {
				writer.write("@ATTRIBUTE \"" + nomeAp.get(i) + "\" REAL\n");
			}

			writer.write("@ATTRIBUTE class {");
			for (int i = 0; i < nomeSalas.size(); i++) {
				if (i + 1 == nomeSalas.size()) {
					writer.write(nomeSalas.get(i) + "}\n\n");
				} else {
					writer.write(nomeSalas.get(i) + ",");
				}
			}

			writer.write("@DATA\n");

			for (int i = 0; i < nomeSalas.size(); i++) {
				/*for (int j = 1; j <= 5; j++) { // contagem */
				for (int k = 0; k < nomeAp.size(); k++) {
					for (int m = 0; m < aps.size(); m++) {
						if (aps.get(m).getBSSID()
								.equals(nomeAp.get(k))
								&& aps.get(m).getSala()
								.equals(nomeSalas.get(i))) /*
									&& Integer.parseInt(aps.get(m)
									.getContagem()) == j) */ {
							sinal = aps.get(m).getRSSI() + ",";
							break;
						}
					}
					if (sinal != "") {
						writer.write(sinal);
						System.out.println("------ geraArffJson - Rssi: " + sinal);
						sinal = "";
					} else {
						writer.write("0,");
						System.out.println("------ geraArffJson - Rssi: " + sinal);
						sinal = "";
					}

				}
				writer.write(nomeSalas.get(i) + "\n");
				/*}*/
			}
		} catch (IOException ex) {
			// report
			return ex.toString();
		} finally {
			try {
				writer.close();
				return "1";
			} catch (Exception ex) {
				return ex.toString();
			}
		}
	}




	


}
